package ch.fhnw.apsi;

import java.io.IOException;
import java.util.Objects;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ch.fhnw.apsi.beans.ErrorMessage;
import ch.fhnw.apsi.beans.Index;
import ch.fhnw.apsi.services.Register;
import ch.fhnw.apsi.services.ServiceResult;
import ch.fhnw.apsi.services.SetPW;
import ch.fhnw.apsi.templates.TemplateEngine;
import ch.fhnw.apsi.templates.TemplateEngineFactory;

/**
 * Servlet implementation class HTMLForm
 */
@WebServlet(name = "HTMLForm", urlPatterns = { "/app/*" })
public class HTMLForm extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public HTMLForm() {
    super();
  }

  @Override
  public void init(final ServletConfig config) throws ServletException {
    // nothing to initialize...
  }

  @Override
  protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
      IOException {
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    Page page = (Page) request.getAttribute("page");
    if (page != Page.ERROR)
      switch (request.getPathInfo()) {
      case "/login":
        page = Page.LOGIN;
        break;
      case "/register":
        page = Page.REGISTER;
        break;
      case "/setpw":
        page = Page.SETPW;
        break;
      case "/":
        page = Page.INDEX;
        break;
      case "/success":
        page = Page.SUCCESS;
        break;
      default:
        page = Page.ERROR;
        break;
      }
    request.setAttribute("page", page);
    renderPage(request, response);
  }

  @Override
  protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
      IOException {
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    Page page = (Page) request.getAttribute("page");
    if (page != Page.ERROR)
      switch (request.getPathInfo()) {
      case "/login":
        page = Page.LOGIN;
        break;
      case "/register":
        page = Page.REGISTER;
        break;
      case "/setpw":
        page = Page.SETPW;
        break;
      case "/success":
      case "/":
        // Nur GET ist erlaubt.
        page = Page.ERROR;
        request.setAttribute("error", "HTTP-Methode ''POST'' ist in diesem Kontext nicht erlaubt!");
        break;
      default:
        page = Page.ERROR;
        break;
      }
    request.setAttribute("page", page);
    renderPage(request, response);
  }

  private static void renderPage(final HttpServletRequest request, final HttpServletResponse response) {
    // final HttpSession session = request.getSession(true);
    final TemplateEngine templateEngine = TemplateEngineFactory.createTemplateEngine();
    ServiceResult result = new ServiceResult(new Object(), (Page) request.getAttribute("page"));
    try {
      switch (result.getPage()) {
      case LOGIN:
      case SUCCESS:
        break;
      case REGISTER:
        result = new Register().process(request, response);
        break;
      case INDEX:
        result.setBean(new Index());
        break;
      case SETPW:
        result = new SetPW().process(request, response);
        break;
      case ERROR:
        // Some Filter or other code already determined that this is an error.
        throw new Exception("Fitlered.");
      default:
        request.setAttribute("status", 404);
        request.setAttribute("error", "Ressource nicht verfügbar.");
        throw new Exception("Bad URL...");
      }
    } catch (final Exception e) {
      final ErrorMessage error = new ErrorMessage();
      error.setError(Objects.toString(request.getAttribute("error"), "Fatal Error. No error message available."));
      if (request.getAttribute("status") instanceof Integer)
        error.setStatus((Integer) request.getAttribute("status"));
      else
        error.setStatus(500);
      result.setBean(error);
      result.setPage(Page.ERROR);
    }
    try {
      response.setCharacterEncoding("UTF-8");
      response.setHeader("Cache-Control", "no-cache");
      response.setHeader("Pragma", "no-cache");
      response.setContentType("application/xhtml+xml"); // http://www.w3.org/TR/xhtml-media-types/#application-xhtml-xml
      if (result.getPage() == Page.ERROR)
        response.setStatus(Integer.valueOf(((ErrorMessage) result.getBean()).getStatus()));
      else
        response.setStatus(200);
      // Note: we do NOT use response.sendError(...) as it might contain information about the system.
      templateEngine.writeHTML(result, response.getWriter());
    } catch (final Exception e) {
      try {
        response.getWriter().write("fatal error :-(");
      } catch (final IOException e1) {
        // now I can't do anything...
      }
    }
  }
}
